#!/usr/bin/python
from netFunctions import *
import threading
import socket
import dpkt

class NetRawListener(threading.Thread):
    '''
    Raw Socket Network Listener class. Only use threading, socket and dpkt packages.
    usage:
        from netRawListener import NetRawListener
        mysniffer = NetRawListener()
        mysniffer.start()
    '''
    def __init__(self,raw=False):
        ''' Class constructor, raw=True would cause the listener to store incoming packet without parsing them '''
        threading.Thread.__init__(self)
        self.__running = False
        self.__sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW,socket.htons(3))
        self.__sock.setsockopt(self.__sock, socket.SOL_PACKET, socket.PACKET_ADD_MEMBERSHIP, socket.PACKET_MR_PROMISC)
        #self.__sock.bind(("eth0",0))
        self.__inputBuffer = []
        self.__rawBufferMode = raw
            
    def isRunning(self):
        ''' Returns True if the listener thread is running, otherwise will return False '''
        return self.__running
    
    def isRawBuffer(self):
        ''' Returns true if the listener is storing raw data instead of dkpt-parsed data '''
        return self.__rawBufferMode
    
    def bufferLength(self):
        ''' Returns length of buffer '''
        return len(self.__inputBuffer)
    
    def bufferEmpty(self):
        ''' Returns True if the buffer is empty, False otherwise '''
        if self.bufferLength() > 0:
            return False
        else:
            return True
        
    def ___addToBuffer(self,packet):
        ''' Appends received data to the buffer, data are parsed using dkpt if rawmode is set to False '''
        if not self.isRawBuffer():
            packet = dpkt.ethernet.Ethernet(packet)
        self.__inputBuffer.append(packet)
        
    def getData(self,count=-1):
        ''' Returns a list of n buffer entries '''
        if count < 0 or count > self.bufferLength():
            count = self.bufferLength()
        data = self.__inputBuffer[0:count]
        del self.__inputBuffer[0:count]
        return data
        
    def stop(self):
        ''' Attempts to stop the listener soflty '''
        self.__sock.close()
        self.__running = False
    
    def run(self):
        ''' Main routine '''
        self.__running = True
        while self.isRunning():
            packet = self.__sock.recvfrom(4096)[0]
            if len(packet) == 0:
                self.stop()
            else:
                l2 = dpkt.ethernet.Ethernet(packet)
                if l2.type == dpkt.ethernet.ETH_TYPE_IP:
                    l3 = l2.data
                    l4 = l3.data
                    print its(l3.src) +":"+str(l4.sport) + "\t=>\t" + its(l3.dst) +":"+str(l4.dport)
                self.___addToBuffer(packet)